package fr.pud.client.controller;

import java.awt.event.ActionEvent;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.ArrayList;

import javax.swing.AbstractAction;

import org.openstreetmap.gui.jmapviewer.Coordinate;

import fr.pud.client.i18n.LanguagesConstants;
import fr.pud.client.images.ImagesDatabase;
import fr.pud.client.model.Address;
import fr.pud.client.model.Fleet;
import fr.pud.client.model.PUDStation;
import fr.pud.client.model.Queries;
import fr.pud.client.model.Query;
import fr.pud.client.model.Route;
import fr.pud.client.model.Routes;
import fr.pud.client.model.Time;
import fr.pud.client.model.Vehicle;
import fr.pud.client.view.MainFrame;
import fr.pud.server.IServer;
import fr.pud.utils.Properties;
import fr.pud.utils.Tools;

/**
 * The abstract action used to launch the computation on the remote server.
 * Apr 9, 2012 - OSE.
 * @author Simon Devineau, Adrien Hierry, Leopold Houdin, Pierre Reliquet
 *         Ecole des Mines de Nantes
 *         LaunchComputation.java
 */
public class LaunchComputation extends AbstractAction {
    /**
     * a Generated serial ID
     */
    private static final long  serialVersionUID = 4719593574208876791L;
    /**
     * The ip of the server
     */
    public static final String REMOTE_IP        = "192.168.1.14";
    /**
     * The remote server
     */
    private static IServer     remoteServer     = null;

    public static ArrayList<Route> compute(Fleet aFleet, Queries aQueries,
            Properties prop) {
        try {
            System.out.println("Contacting the server ...");
            Registry registry = LocateRegistry.getRegistry(REMOTE_IP,
                    IServer.PORT);
            remoteServer = (IServer) registry.lookup(IServer.NAME);
            System.out.println("Server contacted ! ");
        }
        catch (RemoteException e) {
            e.printStackTrace();
        }
        catch (NotBoundException e) {
            e.printStackTrace();
        }
        if (remoteServer == null) {
            Tools.writeToLogFile(LanguagesConstants.LANGUAGE
                    .getString(LanguagesConstants.SERVER_DOWN),
                    Tools.LOG_FILE_SHOW_JOPTION_PANE);
            return null;
        }
        try {
            return remoteServer.solve(aFleet, aQueries, prop);
        }
        catch (RemoteException e) {
            Tools.writeToLogFile(LanguagesConstants.LANGUAGE
                    .getString(LanguagesConstants.ERROR_COMPUTATION),
                    Tools.LOG_FILE_SHOW_JOPTION_PANE, e.getStackTrace());
            return null;
        }
    }

    /**
     * The default constructor
     */
    public LaunchComputation() {
        this.putValue(NAME, LanguagesConstants.LANGUAGE
                .getString(LanguagesConstants.LAUNCH_COMPUTATION));
        this.putValue(SMALL_ICON, ImagesDatabase.CALCULATOR);
        // firstTest();
        // secondTest();
    }

    /**
     * If the button is pressed, the client part launches the computation on the
     * remote server.
     */
    /*
     * (non-Javadoc)
     * @see
     * java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
     */
    @Override
    public void actionPerformed(ActionEvent aArg0) {
        MainFrame.getMainFrame().setVisible(false);
        // JOptionPane.showMessageDialog(null, LanguagesConstants.LANGUAGE
        // .getString(LanguagesConstants.WAITING_COMPUTATION));
        try {
            Routes.getInstance().setRoutes(
                    compute(Fleet.getInstance(), Queries.getInstance(),
                            new Properties(false, 60)));
        }
        catch (Exception anE) {
            Tools.writeToLogFile(
                    "Error occured during connection with the server",
                    Tools.LOG_FILE_NO_JOPTION_PANE, anE.getStackTrace());
            anE.printStackTrace();
        }
        MainFrame.getMainFrame().setVisible(true);
    }

    /**
     * A test which add some queries to the databases
     */
    public void firstTest() {
        // Creation of the coordinates
        Coordinate c1 = new Coordinate(47.1043174434453, -1.86973555013537);
        Coordinate c2 = new Coordinate(47.1132790390402, -1.93974237889051);
        Coordinate c3 = new Coordinate(46.993094952777, -1.59697584807873);
        Coordinate c4 = new Coordinate(47.1099923271686, -1.7334496602416);
        Coordinate c5 = new Coordinate(47.45067636623979, -2.04524522647262);
        Coordinate c6 = new Coordinate(47.1657695341855, -1.80204925127327);
        // creation of time
        Time t1 = new Time(10, 00);
        Time t2 = new Time(17, 00);
        Time t3 = new Time(9, 00);
        Time t4 = new Time(19, 00);
        // Creation of PUDStation
        PUDStation pud1 = new PUDStation(new Address(c1), t1, t2, 60);
        PUDStation pud2 = new PUDStation(new Address(c2), t1, t2, 60);
        PUDStation pud3 = new PUDStation(new Address(c3), t3, t4, 60);
        PUDStation pud4 = new PUDStation(new Address(c4), t3, t2, 60);
        PUDStation pud5 = new PUDStation(new Address(c5), t3, t4, 60);
        PUDStation pud6 = new PUDStation(new Address(c6), t1, t2, 60);
        // Creation of requests
        Query r1 = new Query(pud1, pud2, 120, 5);
        Query r2 = new Query(pud1, pud3, 60, 15);
        Query r3 = new Query(pud1, pud4, 90, 5);
        Query r4 = new Query(pud1, pud5, 190, 5);
        Query r5 = new Query(pud1, pud6, 20, 5);
        Query r6 = new Query(pud2, pud1, 120, 5);
        Query r7 = new Query(pud2, pud3, 60, 15);
        Query r8 = new Query(pud2, pud4, 90, 5);
        Query r9 = new Query(pud2, pud5, 190, 5);
        Query r10 = new Query(pud2, pud6, 20, 5);
        // Add of the requests to the singleton
        Queries.getInstance().addQuery(r1);
        Queries.getInstance().addQuery(r2);
        Queries.getInstance().addQuery(r3);
        Queries.getInstance().addQuery(r4);
        Queries.getInstance().addQuery(r5);
        Queries.getInstance().addQuery(r6);
        Queries.getInstance().addQuery(r7);
        Queries.getInstance().addQuery(r8);
        Queries.getInstance().addQuery(r9);
        Queries.getInstance().addQuery(r10);
        // Creation of vehicules
        Vehicle v1 = new Vehicle(10, 500, pud1, pud1);
        Vehicle v2 = new Vehicle(19, 700, pud2, pud2);
        // Creation of fleet
        Fleet f = Fleet.getInstance();
        f.add(v1);
        f.add(v2);
    }

    /**
     * A test which add some queries to the databases
     */
    public void secondTest() {
        // Fontaine
        Coordinate c1 = new Coordinate(47.214730752945, -1.56192145040775);
        // Bouvier
        Coordinate c2 = new Coordinate(47.2333525997089, -1.54041651694579);
        // Mansart
        Coordinate c3 = new Coordinate(47.235287958646, -1.50641504833291);
        // Eucalyptus
        Coordinate c4 = new Coordinate(47.2252669934835, -1.5133325910053);
        // Clemenceau
        Coordinate c5 = new Coordinate(47.2193258618935, -1.54675676157981);
        // Mines
        Coordinate c6 = new Coordinate(47.2820872990421, -1.5197284686193);
        // Cabinet
        Coordinate c7 = new Coordinate(47.2305180170751, -1.52383764281852);
        // creation of time
        Time t1 = new Time(9, 00);
        Time t2 = new Time(17, 00);
        // Creation of PUDStation
        PUDStation pud1 = new PUDStation(new Address(c1), t1, t2, 60);
        PUDStation pud2 = new PUDStation(new Address(c2), t1, t2, 60);
        PUDStation pud3 = new PUDStation(new Address(c3), t1, t2, 60);
        PUDStation pud4 = new PUDStation(new Address(c4), t1, t2, 60);
        PUDStation pud5 = new PUDStation(new Address(c5), t1, t2, 60);
        PUDStation pud6 = new PUDStation(new Address(c6), t1, t2, 60);
        PUDStation pud7 = new PUDStation(new Address(c7), t1, t2, 60);
        // Creation of requests
        Query r1 = new Query(pud7, pud1, 600, 5);
        Query r2 = new Query(pud7, pud2, 600, 5);
        Query r3 = new Query(pud7, pud3, 600, 5);
        Query r4 = new Query(pud7, pud4, 600, 5);
        Query r5 = new Query(pud7, pud5, 600, 5);
        Query r6 = new Query(pud7, pud6, 600, 5);
        // Add of the requests to the singleton
        Queries.getInstance().addQuery(r1);
        Queries.getInstance().addQuery(r2);
        Queries.getInstance().addQuery(r3);
        Queries.getInstance().addQuery(r4);
        Queries.getInstance().addQuery(r5);
        Queries.getInstance().addQuery(r6);
        Vehicle v1 = new Vehicle(50, 600, pud7, pud7);
        Vehicle v2 = new Vehicle(50, 600, pud7, pud7);
        Fleet.getInstance().add(v1);
        Fleet.getInstance().add(v2);
    }
}
